package org.yxj.lib_downfile.m;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import com.google.gson.Gson;
import org.yxj.lib_downfile.LogUtil;
import org.yxj.lib_downfile.bean.DownFileBean;
import org.yxj.lib_downfile.down.DownFileTask;
import org.yxj.lib_downfile.i.DownFileProgressListener;
import org.yxj.lib_downfile.i.DownListener;
import org.yxj.lib_downfile.i.ResultListener;
import java.io.File;
import java.io.IOException;

/**
 * 下载文件管理类
 *
 * @author yxj on 2023/11/3
 */
public class DownFileManager {

    private Context context;

    private static DownFileManager manager;

    private DownFileManager() {
    }

    public static DownFileManager getInstance() {
        if (null == manager) {
            synchronized (DownFileManager.class) {
                if (null == manager) {
                    manager = new DownFileManager();
                }
            }
        }
        return manager;
    }


    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        this.context = context;
        //初始化缓存存储数据库
        AppSQLiteManager.getInstance().init(context);
    }


    /**
     * 下载对象
     */
    private DownFileTask downFileTask;
    /**
     * 文件保存路径
     */
    private String filePath = "";
    /**
     * 下载文件地址
     */
    private String fileUrl = "";
    /**
     * 回调
     */
    private DownListener listener;

    /**
     * 是否正在下载中
     *
     * @return
     */
    public boolean isDowning() {
        return downFileTask != null && downFileTask.isRunning();
    }

    /**
     * 是否正在下载中
     *
     * @return
     */
    public boolean isHaveFile() {
        File file = new File(filePath);
        if (!file.exists()) {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 是否有文件下载地址
     *
     * @return
     */
    public boolean isHaveFileUrl() {
        return TextUtils.isEmpty(fileUrl);
    }

    /**
     * 必传文件地址
     *
     * @param filePath
     * @return
     */
    public DownFileManager saveFilePath(String filePath) {
        this.filePath = filePath;
        return this;
    }


    /**
     * 下载回调
     *
     * @param listener
     * @return
     */
    public DownFileManager listener(DownListener listener) {
        this.listener = listener;
        return this;
    }


    /**
     * 必传下载地址
     *
     * @param fileUrl
     * @return
     */
    public DownFileManager downUrl(String fileUrl) {
        this.fileUrl = fileUrl;
        return this;
    }



    /**
     * 默认进度
     */
    public void defaultProgress(String fileUrl,ResultListener<Long> resultListener) {
        if (!TextUtils.isEmpty(fileUrl)) {
            DownFileBean b = AppSQLiteManager.getInstance().getDownFileDao().queryByFileUrl(fileUrl);
            if (b != null  ) {
                if (!TextUtils.isEmpty(b.filePath)){
                    File file=new File(b.filePath);
                    if (file.exists()){
                        LogUtil.LOG_V("[DownFileDao]->" + new Gson().toJson(b));
                        if (resultListener != null)
                            resultListener.onResult((long) format(b.currentProgress, b.fileTotalLength));
                    }
                }else {
                    AppSQLiteManager.getInstance().getDownFileDao().clear();
                }
            }
        }
    }




    /**
     * 开始下载
     */
    public void start() {
        LogUtil.LOG_V("[filePath]->filePath = " + filePath);
        //1、文件路径必须传
        if (TextUtils.isEmpty(filePath)) {
            LogUtil.TOAST(context, "文件存储路径不存在！");
            return;
        }

        //2、文件是否存在
        File file = new File(filePath);
        if (isHaveFile()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.TOAST(context, "下载文件创建失败！");
                return;
            }
        }

        //3、是否正在下载
        if (isDowning()) {
            LogUtil.TOAST(context, "文件正在下载！");
            return;
        }

        //3、是否正在下载
        if (isDowning()) {
            LogUtil.TOAST(context, "文件正在下载！");
            return;
        }

        //4、下载地址不存在
        if (isHaveFileUrl()) {
            LogUtil.TOAST(context, "文件下载地址不存在！");
            return;
        }
        DownFileBean downFileBean = new DownFileBean();
        downFileBean.fileUrl = fileUrl;
        downFileBean.filePath = filePath;
        downFileTask = new DownFileTask(downFileBean);
        downFileTask.setDownFileProgressListener(progressListener);
        downFileTask.start();
    }



    /**
     * 是否已经下载
     * @return
     */
    public void isFileDowned(String filePath,String fileUrl,final ResultListener<Boolean> resultListener){
        DownFileBean downFileBean = new DownFileBean();
        downFileBean.filePath = filePath;
        downFileBean.fileUrl = fileUrl;
        new DownFileTask(downFileBean).isHaveFile(new ResultListener<Boolean>() {
            @Override
            public void onResult(Boolean aBoolean) {
                if (resultListener!=null)
                    resultListener.onResult(aBoolean);
            }
        });
    }



    /**
     * 停止下载
     */
    public void stop() {
        if (downFileTask != null) {
            downFileTask.cancel();
            reset();
        }
    }


    /**
     * 重置
     */
    public void reset() {
        fileUrl = null;
        filePath = null;
        listener = null;
        if (downFileTask != null) {
            downFileTask.cancel();
            downFileTask = null;
        }
    }


    private DownFileProgressListener progressListener = new DownFileProgressListener() {

        @Override
        public void onComplete(DownFileTask task, DownFileBean downFileBean) {
            super.onComplete(task, downFileBean);
            LogUtil.LOG_V("[DownFileProgressListener]->onComplete()" + downFileBean.filePath);
            if (listener != null) {
                listener.onComplete(downFileBean);
            }
        }

        @Override
        public void onFail(DownFileTask task, String error) {
            super.onFail(task, error);
            LogUtil.LOG_V("[DownFileProgressListener]->onFail()");
            if (listener != null) {
                listener.onFail(error);
            }
        }

        @Override
        public void onPending(DownFileTask task, long progress, long total) {
            super.onPending(task, progress, total);
            LogUtil.LOG_V("[DownFileProgressListener]->onPending()");
            if (listener != null) {
                listener.onPrepare("onPending", (long) format(progress, total), total);
            }
        }


        @Override
        public void onProgress(DownFileBean downFileBean, long progress, long total) {
            LogUtil.LOG_V("[DownFileProgressListener]->onProgress()");
            downFileBean.currentProgress = progress;
            downFileBean.fileTotalLength = total;
            boolean b = AppSQLiteManager.getInstance().getDownFileDao().isHave(downFileBean.fileUrl);
            if (b) {
                LogUtil.LOG_V("[DownFileProgressListener]->update()");
                AppSQLiteManager.getInstance().getDownFileDao().update(downFileBean);
            } else {
                AppSQLiteManager.getInstance().getDownFileDao().insert(downFileBean);
                LogUtil.LOG_V("[DownFileProgressListener]->insert()");
            }
            if (listener != null) {
                listener.onProgress((long) format(progress, total));
            }
        }


        @Override
        public void onHaveDownloaded(final File file) {
            super.onHaveDownloaded(file);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    LogUtil.TOAST(context, "文件已下载：" + file.getPath());
                }
            });
        }

        @Override
        public void cancel(DownFileTask task) {
            super.cancel(task);
        }
    };


    /**
     * @param soFarBytes
     * @param totalBytes
     */
    private float format(final long soFarBytes, final long totalBytes) {
        float p = (float) (soFarBytes * 1.0 / totalBytes) * 100;
        LogUtil.LOG_V("[format]->p=" + p);
        return p;
    }


    /**
     * @param runnable
     */
    public void runOnUiThread(Runnable runnable) {
        if (context != null) {
            new Handler(context.getMainLooper()).post(runnable);
        }
    }
}
